package com.spbdx.system.service.workflow;

import com.spbdx.common.utils.DateUtils;
import com.spbdx.common.utils.SecurityUtils;
import com.spbdx.system.domain.EventOrder;
import com.spbdx.system.domain.EventOrderFlow;
import com.spbdx.system.mapper.EventOrderFlowMapper;
import com.spbdx.system.mapper.EventOrderMapper;
import com.spbdx.system.service.workflow.support.MachineStatus;
import com.spbdx.system.service.workflow.support.MachineStatusEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import java.util.EnumSet;

/**
 * 状态机配置
 * 维保单状态配置
 *
 * @author chenwei
 * @version 1.0
 * @date 2024/8/6 16:25
 */
@Slf4j
@Configuration
@EnableStateMachine(name = "machineState")
public class MachineStateConfig extends EnumStateMachineConfigurerAdapter<MachineStatus, MachineStatusEvent> {

    @Autowired
    private EventOrderMapper eventOrderMapper;

    @Autowired
    private EventOrderFlowMapper eventOrderFlowMapper;

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    @Override
    public void configure(StateMachineStateConfigurer<MachineStatus, MachineStatusEvent> states) throws Exception {
        states.withStates().initial(MachineStatus.NEW).states(EnumSet.allOf(MachineStatus.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<MachineStatus, MachineStatusEvent> transitions) throws Exception {
        transitions.withExternal()
                //新订单状态到已接单
                .source(MachineStatus.NEW).target(MachineStatus.ACCEPTED)
                .event(MachineStatusEvent.ACCEPT)
                .and()
                .withExternal()
                //已接单状态到已签到
                .source(MachineStatus.ACCEPTED).target(MachineStatus.CHECKED_IN)
                .event(MachineStatusEvent.CHECK_IN)
                .and()
                .withExternal()
                //已签到状态到已完成维保
                .source(MachineStatus.CHECKED_IN).target(MachineStatus.MAINTENANCE_FINISHED)
                .event(MachineStatusEvent.MAINTENANCE_FINISH)
                .and()
                .withExternal()
                //已完成维保状态到已评价
                .source(MachineStatus.MAINTENANCE_FINISHED).target(MachineStatus.FINISHED)
                .event(MachineStatusEvent.REVIEW);
    }


    /**
     * 持久化配置
     *
     * @return
     */
    @Bean(name = "machinePersister")
    public DefaultStateMachinePersister<MachineStatus, MachineStatusEvent, EventOrder> machinePersister() {
        return new DefaultStateMachinePersister<>(new StateMachinePersist<MachineStatus, MachineStatusEvent, EventOrder>() {

            @Override
            public void write(StateMachineContext<MachineStatus, MachineStatusEvent> stateMachineContext, EventOrder eventOrder) {
                //开始事务 手动提交，用默认事务多个表修改不能同步，怀疑是异步执行的事务
                TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
                try {
                    //TODO 更新order status，并在订单流中添加新的记录
                    eventOrder.setOrderStatus(stateMachineContext.getState().getCode());
                    eventOrderMapper.updateEventOrder(eventOrder);

                    EventOrderFlow eventOrderFlow = new EventOrderFlow();
                    eventOrderFlow.setOrderId(eventOrder.getOrderId());
                    eventOrderFlow.setEventId(eventOrder.getEventId());
                    eventOrderFlow.setType(eventOrder.getType());
                    eventOrderFlow.setOrderStatus(stateMachineContext.getState().getCode());
                    eventOrderFlow.setCreateBy(SecurityUtils.getUsername());
                    eventOrderFlow.setCreateTime(DateUtils.getNowDate());
                    eventOrderFlowMapper.insertEventOrderFlow(eventOrderFlow);
                    platformTransactionManager.commit(transactionStatus);
                } catch (Exception e) {
                    platformTransactionManager.rollback(transactionStatus);
                    log.error("状态机持久化事件发生异常，eventOrderId = {}", eventOrder.getOrderId(), e);
                    throw new RuntimeException("状态机持久化事件发生异常:" + e.getMessage());
                }
            }

            @Override
            public StateMachineContext<MachineStatus, MachineStatusEvent> read(EventOrder eventOrder) {
                MachineStatus state = MachineStatus.valueOf(eventOrder.getOrderStatus().toUpperCase()); // 假设状态存储在data的state字段中
                // 构建并返回StateMachineContext
                return new DefaultStateMachineContext<>(state, null, null, null);
            }
        });
    }

}